package net.butfly.bus.server;

import java.io.InputStream;

import net.butfly.albacore.exception.SystemException;
import net.butfly.bus.Constants;
import net.butfly.bus.Constants.FilterSide;
import net.butfly.bus.Request;
import net.butfly.bus.Response;
import net.butfly.bus.config.bean.NodeBean;
import net.butfly.bus.config.loader.ClasspathConfigLoad;
import net.butfly.bus.context.Context;
import net.butfly.bus.filter.Filter;
import net.butfly.bus.filter.FilterBase;
import net.butfly.bus.filter.FilterChain;
import net.butfly.bus.impl.Invoker;
import net.butfly.bus.router.Router;
import net.butfly.bus.server.config.ServerConfig;
import net.butfly.bus.server.invoker.InvokerTypeFactory;
import net.butfly.bus.server.router.DefaultRouter;

public class Server {
	private final String serverId;
	private ServerConfig config;

	private FilterChain chain;
	private Router router;

	public Server(String config) {
		this.initialize(config);
		this.config = parser.parse();
		this.router = new DefaultRouter(this.config);
		this.chain = new FilterChain(getConfig().getFilterBeanList(), server, FilterSide.SERVER);
		this.serverId = this.config.getBusID();
	}

	public String getServerId() {
		return this.serverId;
	}

	public Response execute(Request request) throws Exception {
		if (request == null)
			throw new SystemException(Constants.UserError.BAD_REQUEST, "交易请求不能为空!");
		if (request.code() == null || "".equals(request.code().trim()))
			throw new SystemException(Constants.UserError.BAD_REQUEST, "交易码不能为空！");
		if (request.version() == null || "".equals(request.version().trim()))
			throw new SystemException(Constants.UserError.BAD_REQUEST, "交易版本号不能为空！");
		Context.CURRENT.putAll(request.context());
		Response response = new Response();
		chain.execute(request, response);
		return response;
	}

	public ServerConfig getConfig() {
		return this.config;
	}

	private final Filter server = new FilterBase() {// 执行主应用逻辑
		@Override
		public void execute(Request request, Response response) throws Exception {
			ServerConfig c = Server.this.config;
			String nodeId = router.route(request.code(), request.version());
			if (nodeId == null) {
				String[] nodes = c.getNodeIDsByMatching(request.code());
				if (null != nodes && nodes.length > 0)
					nodeId = nodes[0];
			}
			NodeBean nb = c.getNodeBean(nodeId);
			Invoker invoker = InvokerTypeFactory.getInvoker(nb.getInvoker().getType(), nb.getInvoker().getConfig());
			response.copyFrom(invoker.invoke(request, response));
		}
	};

	private ClasspathConfigLoad loader;
	private XMLConfigServerParser parser;

	private void initialize(String configLocation) {
		this.loader = new ClasspathConfigLoad(configLocation);
		InputStream is = loader.load();
		// load local / internal config
		if (null == is) {
			loader = new ClasspathConfigLoad(Constants.Configuration.DEFAULT_SERVER_CONFIG);
			is = loader.load();
			if (null == is) {
				loader = new ClasspathConfigLoad(Constants.Configuration.INTERNAL_SERVER_CONFIG);
				is = loader.load();
			}
		}
		if (null == is)
			throw new SystemException(Constants.UserError.CONFIG_ERROR, "Bus configurations invalid: " + configLocation);
		this.parser = new XMLConfigServerParser(loader.load());
	}
}